package main

import (
	"encoding/json"
	"fmt"
)

type Monster struct {
	Name     string `json:"monster_name"` // 如果希望序列化后的字段变成小写或别的名称, 可以自己指定, 这里就是反射机制
	Age      int
	Birthday string
	Salary   float64
	Skill    string
}

// ==========Json==========
// 1、JSON(JavaScript Object Notation)是一种轻量级的数据交换格式
// 2、JSON易于机器解析和生成, 并有效地提升网络传输效率, 通常程序在网络传输时会现将数据(结构体、map等)序列化成json字符串
//    到接收方得到json字符串时, 再反序列化恢复成原来的数据类型.
// 3、在JS语言中, 一切都是对象. 因此, 任何类型的数据都可以通过JSON表示.
// 4、JSON键值对是用来保存数据的一种方式
// 5、JSON序列化是指, 将有key-value结构的数据类型(比如结构体、map、切片)序列化成json字符串的操作
// 6、将json字符串反序列化成对应的数据类型的操作

// 序列化结构体
func SerializeStruct() {
	monster := Monster{
		Name:     "牛魔王",
		Age:      500,
		Birthday: "20200101",
		Salary:   1000,
		Skill:    "Fight",
	}
	// 将monster序列化
	monsterByte, _ := json.Marshal(monster)
	fmt.Printf("序列化后的结果是: %v\n", string(monsterByte))
	// 序列化后的结果是: {"Name":"牛魔王","Age":500,"Birthday":"20200101","Salary":1000,"Skill":"Fight"}
}

// 序列化map
func SerializeMap() {
	m := make(map[string]string)
	m["Name"] = "Max"
	m["Gender"] = "Male"

	mapByte, _ := json.Marshal(m)
	fmt.Printf("序列化后的结果是: %v\n", string(mapByte))
	// 序列化后的结果是: {"Gender":"Male","Name":"Max"}
}

// 切片序列化
func SerializeSlice() {
	var slice []map[string]interface{}
	m1 := make(map[string]interface{})
	m1["name"] = "jack"
	m1["age"] = 7
	m2 := make(map[string]interface{})
	m2["school"] = "mit"
	m2["location"] = "china"
	slice = append(slice, m1, m2)

	sliceByte, _ := json.Marshal(slice)
	fmt.Printf("序列化后的结果是: %v\n", string(sliceByte))
	// 序列化后的结果是: [{"age":7,"name":"jack"},{"location":"china","school":"mit"}]
}

// 对基本数据类型序列化
func SerializeBase() {
	num1 := 1.2
	baseByte, _ := json.Marshal(num1)
	fmt.Printf("序列化后的结果是: %v\n", string(baseByte))
	// 序列化后的结果是: 1.2
}

// 反序列化结构体
func UnSerializeStruct() {
	var monster Monster
	// 这里的字符串是手动粘贴过来的, 需要在字段前的"加上\, 如果是程序外部读取到的json字符串, 就不需要手动加\
	str := "{\"monster_name\":\"牛魔王\",\"Age\":500,\"Birthday\":\"20200101\",\"Salary\":1000,\"Skill\":\"Fight\"}"
	err := json.Unmarshal([]byte(str), &monster) // 必须要传变量的指针
	if err != nil {
		fmt.Println("反序列化失败")
	} else {
		fmt.Println("结构体反序列化: ", monster, monster.Name)
	}
}

// 反序列化map
func UnSerializeMap() {
	var m map[string]string
	str := "{\"Gender\":\"Male\",\"Name\":\"Max\"}"
	// 反序列化map不需要make, Unmarshal会自动make
	err := json.Unmarshal([]byte(str), &m)
	if err != nil {
		fmt.Println("反序列化失败")
	} else {
		fmt.Println("map反序列化: ", m)
	}
}

// 反序列化切片
func UnSerializeSlice() {
	var slice []map[string]interface{}
	str := "[{\"age\":7,\"name\":\"jack\"},{\"location\":\"china\",\"school\":\"mit\"}]"
	err := json.Unmarshal([]byte(str), &slice)
	if err != nil {
		fmt.Println("反序列化失败")
	} else {
		fmt.Println("切片反序列化", slice)
		fmt.Println(slice[0]["name"])
	}
}

func main() {
	SerializeStruct()
	SerializeMap()
	SerializeSlice()
	SerializeBase()

	UnSerializeStruct()
	UnSerializeMap()
	UnSerializeSlice()
}
